package com.example.fdbus

import android.util.Log
import com.example.fdbus.request.RequestBean
import java.lang.reflect.Method
import java.util.concurrent.ConcurrentHashMap

class NameCenter {
    private val clazzHashMap: ConcurrentHashMap<String, Class<*>> = ConcurrentHashMap()
    private val methodsHashMap: ConcurrentHashMap<String, ConcurrentHashMap<String, Method>> =
        ConcurrentHashMap()

    private val objectsHashMap: ConcurrentHashMap<String, Any> = ConcurrentHashMap()

    private val TAG = NameCenter::class.java.name

    fun register(clazz: Class<*>) {
        clazzHashMap[clazz.name] = clazz

        // 注册函数
        registerAllMethod(clazz)
    }

    fun putObject(className: String, instance: Any) {
        objectsHashMap.put(className, instance)
    }

    fun getObject(className: String): Any? {
        return objectsHashMap.get(className)
    }

    private fun registerAllMethod(clazz: Class<*>) {
        var methodMap: ConcurrentHashMap<String, Method>? = null
        Log.i(TAG, "registerAllMethod: ${clazz.name}")
        clazz.declaredMethods.forEach { method ->
            Log.i(TAG, "registerAllMethod: method name ${method.name}")
            methodMap = methodsHashMap.get(clazz.name)
            if (methodMap == null) {
                methodMap = ConcurrentHashMap<String, Method>()

                methodsHashMap.put(clazz.name, methodMap!!)
            }
            val signature = generateSignature(method)
            Log.i(TAG, "registerAllMethod: signature $signature")
            methodMap?.put(signature, method)
        }


    }

    fun getMethod(requestBean: RequestBean): Method {
        val methodMap = methodsHashMap.get(requestBean.className)

        require(methodMap != null)

        val paramString = generateSignature(requestBean)

        return methodMap.get(paramString)!!
    }

    private fun generateSignature(method: Method?): String {
        val stringBuilder = StringBuilder()
        stringBuilder.append(method!!.name)
        val params = method.parameterTypes
        if (params.isEmpty())  {
            return method.name
        }
        params.forEach {
            Log.i(TAG, "generateSignature: ${it.name}")
            stringBuilder.append("-").append(it.name)
        }

        return stringBuilder.toString()
    }

    private fun generateSignature(requestBean: RequestBean): String {
        val stringBuilder = StringBuilder()

        stringBuilder.append(requestBean.methodName)

        requestBean.requestParamters.forEachIndexed { index, requestParamter ->
            stringBuilder.append("-").append(requestParamter!!.parameterClassName)
        }

        return stringBuilder.toString()
    }

    fun getClassType(parameterClassName: String): Class<*>? {
        try {
            return Class.forName(parameterClassName)
        } catch (e: ClassNotFoundException) {
            e.printStackTrace()
        }
        return null
    }
}